package poker;
import java.util.LinkedList;

public class Poker
{
	private Talia talia;				//talia kart
	private OstatniaKarta last_card;	//ostatnio wybrana karta z talii
	private Karta karty[];				//tablica kart graczy
	private static int liczba_graczy;
	public Poker()
	{
		talia = null;
		last_card = new OstatniaKarta();
		last_card.ustaw_max_graczy(4);
		karty = new Karta[20];
		liczba_graczy = 1;
	}
	
	public static void main(String args[])
	{	
		int ilosc_graczy = 1;
		if (args.length == 1)
		{	
			try
			{
				ilosc_graczy = Integer.parseInt(args[0]);
			}
			catch (NumberFormatException nfe)
			{
				System.out.println("Podano wartosc nie bedaca liczba lub "
						+ "w nie odpowiednim formacie");
				System.exit(1);
			}
			if (ilosc_graczy > 0 && ilosc_graczy < 5)
			{
				Poker poker = new Poker();
				poker.talia = new Talia();
				poker.rozgrywka(poker, ilosc_graczy);
			}
		}
	}
	
	private void rozgrywka(Poker a, int ilosc_graczy)
	{
		int liczba_botow = 4 - liczba_graczy;
		liczba_graczy = ilosc_graczy + liczba_botow;
		
		if (ilosc_graczy > 0)
		{
			Gracz gracz [] = new Gracz [ilosc_graczy];
			
			for (int i = 0; i < ilosc_graczy; ++i)
			{	
				gracz[i] = new Gracz("gracz" + Integer.toString(i), 
									last_card, talia, karty);
				gracz[i].start();
			}
			
			if (liczba_botow > 0)
			{
				Bot bot[] = new Bot [liczba_botow];

				for (int i = 0; i < liczba_botow; ++i)
				{
					bot[i] = new Bot(("bot" + Integer.toString(i)), last_card, 
										talia, karty);
					bot[i].start();
				}
			}
			
			while (last_card.stan_gry() < 4)
			{
				try
				{
					Thread.sleep(300);
				} catch (InterruptedException e)
				{
					e.printStackTrace();
				}	
			}
			rozpoznaj_karty();
		}
	}

	private void rozpoznaj_karty()
	{	
		sortuj();
		int ranking[] = new int [liczba_graczy];
		int indeks = 0;
		
		for (int i = 0; i < liczba_graczy * 5; i += 5)
		{			
			if (czy_poker(i))
				ranking[indeks] = 1;
			else if (czy_czworka(i))
				ranking[indeks] = 2;
			else if (czy_full(i))
				ranking[indeks] = 3;
			else if (czy_kolor(i))
				ranking[indeks] = 4;
			else if (czy_strit(i))
				ranking[indeks] = 5;
			else if (czy_trojka(i))
				ranking[indeks] = 6;
			else if (czy_dwie_pary(i))
				ranking[indeks] = 7;
			else if (czy_para(i))
				ranking[indeks] = 8;
			else
				ranking[indeks] = 9;

			++indeks;
		}
		
		int min = 9;
		LinkedList<Integer> lista = new LinkedList<Integer>();
		
		for (int i = 0; i < liczba_graczy; ++i)
			if (min > ranking[i])
				min = ranking[i];
		
		for (int i = 0; i < liczba_graczy; ++i)
			if (min == ranking[i])
				lista.add(i+1);
		
		if (lista.size() == 1)
			System.out.println("Wygral: " + karty[(lista.get(0) * 5) - 1].wlasciciel());
		else
		{
			if (min == 2 || min == 3 || min == 6)
			{
				int max = 0;
				for (int i = 0; i < lista.size(); ++i)
					if (karty[(lista.get(i) * 5) - 3].rozpoznaj_wartosc() > max)
						max = karty[(lista.get(i)*5)-3].rozpoznaj_wartosc();
				
				System.out.print("Wygrywajacy to: ");
				for (int i = 0; i < lista.size(); ++i)
					if (karty[(lista.get(i) * 5) -3].rozpoznaj_wartosc() == max)
						System.out.print(karty[(lista.get(i) * 5) - 3].wlasciciel() + " ");
			}
			else if (min == 4 || min == 9 || min == 1 || min == 5)
			{
				int max = karty[(lista.get(0) * 5) - 1].rozpoznaj_wartosc(); 
				for (int i = 1; i < lista.size(); ++i)
					if (max < karty[(lista.get(i) * 5) - 1].rozpoznaj_wartosc())
						max = karty[(lista.get(i) * 5) - 1].rozpoznaj_wartosc();
				
				int licznik = 0;
				for (int i = 0; i < lista.size(); ++i)
					if (karty[(lista.get(i) * 5) - 1].rozpoznaj_wartosc() == max)
					{
						++licznik;
						min = (lista.get(i) * 5) - 1;
					}
				
				if (licznik == 1)
					System.out.println("Wygral: " + karty[min].wlasciciel());
				else
				{
					boolean exit = false;
					licznik = 0;
					int j = 0;
					
					while (j < 4 && !exit)
					{
						max = 0;
						int i = 0;
						licznik = 0;
						++j;

						do
						{
							licznik = 0;
							
							for (int k = 0; k < lista.size(); ++k)
								if (karty[(lista.get(k) * 5) - j].rozpoznaj_wartosc() > max)
									max = karty[(lista.get(i) * 5) - j].rozpoznaj_wartosc();
							
							for (int k = 0; k < lista.size(); ++k)
								if (karty[(lista.get(k) * 5) - j].rozpoznaj_wartosc() == max)
									++licznik;
							
							if (licznik == 1)
							{
								exit = true;
								i = lista.size();
							}
							
							++i;
						} while (i < lista.size());
					}
					
					System.out.print("Wygrywajacy: ");
					for (int i = 0; i < lista.size(); ++i)
						if (karty[(lista.get(i) * 5) - j].rozpoznaj_wartosc() == max)
							System.out.print(karty[(lista.get(i) * 5) -1].wlasciciel() + " ");
				}
			}
			else if (min == 7 || min == 8)
			{
				int max = 0;
				int temp = 0;
					
				LinkedList<Integer> list = new LinkedList<Integer>();
				for (int m = 1; m < 4; ++m)
					for (int k = 0; k < lista.size(); ++k)
						if (karty[(lista.get(k) * 5) - m].compare(
								karty[(lista.get(k) * 5) - (m+1)]))
						{
							list.add(karty[(lista.get(k) * 5) - m].rozpoznaj_wartosc());
							if (karty[(lista.get(k) * 5) - m].rozpoznaj_wartosc() > max)
								max = karty[(lista.get(k) * 5) - m].rozpoznaj_wartosc();
						}
				
				int licznik = 0;
				for (int m = 1; m < 5; ++m)
					for (int k = 0; k < lista.size(); ++k)
						if (karty[(lista.get(k) * 5) - m].rozpoznaj_wartosc() == max)
							++licznik;
							
				if (licznik != 1)
				{
					for (int m = 1; m < 5; ++m)
						for (int k = 0; k < lista.size(); ++k)
							for (int l = 0; l < list.size(); ++l)
								if (karty[(lista.get(k) * 5) - m].rozpoznaj_wartosc() !=
									list.get(l))
								{
									max = karty[(lista.get(k) * 5) - m].rozpoznaj_wartosc();
									temp = m;
								}
				}
				
				System.out.print("Wygrywajacy: ");
				for (int k = 0; k < lista.size(); ++k)
					if (karty[(lista.get(k) * 5) - temp].rozpoznaj_wartosc() == max)
						System.out.print(karty[(lista.get(k) * 5) - temp].wlasciciel() + " ");
			}
		}
	}
	
	private void sortuj()
	{
		for (int i = 0; i < (liczba_graczy * 5) -1; i+= 5)
			for (int k = 0; k < 5; ++k)
				for (int j = i; j < i + 4; ++j)
					if (karty[j].rozpoznaj_wartosc() > karty[j+1].rozpoznaj_wartosc())
						karty[j].zamien(karty[j+1]);
	}
	
	private boolean czy_poker(int i)
	{
		if (czy_podobne(i, true) == 4 && czy_taki_sam_kolor(i) == 4)
			return true;
		
		return false;
	}
	
	private boolean czy_czworka(int i)
	{
		int pomocnicza = 0;
		if (czy_podobne(i, false) != 3)
			return false;
		
		if (!(karty[i].compare(karty[i + 2])))
			pomocnicza = i;
		else
			pomocnicza = i + 4;
		
		for (int j = i; j < i + 5; ++j)
			if (j != pomocnicza && karty[pomocnicza].compare(karty[j]))
				return false;
		
		return true;
	}
	
	private boolean czy_full(int i)
	{
		int pomocnicza = 0;
		if (czy_podobne(i, false) != 3)
			return false;
			
		if (!(karty[i].compare(karty[i + 2])))
			pomocnicza = i;
		else
			pomocnicza = i + 4;
		
		for (int j = i; j < i + 5; ++j)
		{
			if (j != pomocnicza && karty[pomocnicza].compare(karty[j]))
				return true;
		}
		
		return false;
	}
	
	private boolean czy_kolor(int i)
	{
		if (czy_taki_sam_kolor(i) == 4)
			return true;
		
		return false;
	}
	
	private boolean czy_strit(int i)
	{	
		if (czy_podobne(i, true) == 4)
			return true;
		
		return false;
	}
	
	private boolean czy_trojka(int i)
	{
		if (czy_podobne(i, false) != 2)
			return false;
		
		if (karty[i].compare(karty[i + 2]) 
			|| karty[i].compare(karty[i + 2]))
			return true;
		
		return false;
	}
	
	private boolean czy_dwie_pary(int i)
	{
		if (czy_podobne(i, false) == 2)
				return true;
		
		return false;
	}
	
	private boolean czy_para(int i)
	{
		if (czy_podobne(i, false) == 1)
			return true;
		
		return false;
	}
	
	private int czy_podobne(int i, boolean czy_rosnaco)
	{
		int pomocnicza = 0;
		
		if (!czy_rosnaco)
		{
			for (int j = i; j < i + 4; ++j)
				if (karty[j].compare(karty[j+1]))
					++ pomocnicza;
		}
		else
			for (int j = i; j < i + 4; ++j)
				if (karty[j].rozpoznaj_wartosc() + 1 == karty[j+1].rozpoznaj_wartosc())
					++pomocnicza;
					
		return pomocnicza;
	}
	
	private int czy_taki_sam_kolor(int i)
	{
		int pomocnicza = 0;
		
		for (int j = i; j < i + 4; ++j)
			if (karty[j].pokaz_znak().equals(karty[j+1].pokaz_znak()))
				++pomocnicza;
		
		return pomocnicza;
	}
}